package com.tqz.web.flux.demo.exception;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tqz.web.flux.demo.entity.Result;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * <p>springboot默认的webflux异常处理为 {@link DefaultErrorWebExceptionHandler} 。
 * 如果是实现了 {@link ErrorWebExceptionHandler} 接口的话，自定义异常的实现类是不需要指定低级别的order，
 * 如果是实现了 {@link WebExceptionHandler} 接口的话，则需要指定，
 * 因为springboot的 {@link ErrorWebFluxAutoConfiguration} 自动配置类里面注入的是ErrorWebExceptionHandler接口，
 * 并且使用了 {@link Order} 注解指定为-1。
 *
 * @author tianqingzhao
 * @since 2023/3/5 12:09
 */
@Component
public class CustomErrorWebFluxExceptionHandler implements ErrorWebExceptionHandler {

    @Resource
    private ObjectMapper objectMapper;

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        Result result = new Result();
        result.setMsg(ex.getMessage());

        ex.printStackTrace();

        try {
            byte[] bytes = objectMapper.writeValueAsBytes(result);
            return exchange.getResponse().writeWith(Mono.fromSupplier(() -> {
                DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
                return bufferFactory.wrap(bytes);
            }));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return null;
    }
}
